package io.adrainty.bolee.insurance.repository.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.adrainty.bolee.framework.commons.basic.ResponseCode;
import io.adrainty.bolee.framework.commons.exception.AppException;
import io.adrainty.bolee.framework.commons.utils.JsonUtil;
import io.adrainty.bolee.framework.mybatis.utils.MybatisUtil;
import io.adrainty.bolee.insurance.mapper.*;
import io.adrainty.bolee.insurance.models.bo.*;
import io.adrainty.bolee.insurance.models.entity.*;
import io.adrainty.bolee.insurance.repository.IInsuranceRepository;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.BatchResult;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>InsuranceRepositoryImpl</p>
 *
 * @author AdRainty
 * @version V1.0.0
 * @description IInsuranceRepository
 * @since 2025/8/12 10:42:58
 */

@Repository
public class InsuranceRepositoryImpl implements IInsuranceRepository {

    @Resource
    private InsuranceMapper insuranceMapper;

    @Resource
    private InsurancePlanMapper insurancePlanMapper;

    @Resource
    private InsuranceCoefficientMapper insuranceCoefficientMapper;

    @Resource
    private InsuranceConditionMapper insuranceConditionMapper;

    @Resource
    private PlanEarningsMapper planEarningsMapper;

    @Resource
    private PlanSafeguardMapper planSafeguardMapper;

    @Override
    public boolean createInsurance(InsuranceEntity insuranceEntity) {
        InsuranceBO insuranceBO = BeanUtil.toBean(insuranceEntity, InsuranceBO.class);
        boolean result = insuranceMapper.insert(insuranceBO) > 0;
        if (!result) return false;
        BeanUtil.copyProperties(insuranceBO, insuranceEntity);
        return true;
    }

    @Override
    public boolean updateInsurance(InsuranceEntity insuranceEntity) {
        InsuranceBO insuranceBO = BeanUtil.toBean(insuranceEntity, InsuranceBO.class);
        return insuranceMapper.updateById(insuranceBO) > 0;
    }

    @Override
    public InsuranceEntity getInsuranceById(Long insuranceId) {
        InsuranceBO insuranceBO = insuranceMapper.selectById(insuranceId);
        return BeanUtil.toBean(insuranceBO, InsuranceEntity.class);
    }

    @Override
    public IPage<InsuranceEntity> getInsurancePage(Integer pageNum, Integer pageSize, InsuranceEntity insuranceEntity) {
        Wrapper<InsuranceBO> wrapper = getInsuranceWrapper(insuranceEntity);
        Page<InsuranceBO> page = new Page<>(pageNum, pageSize);
        if (wrapper == null) {
            return new Page<>(pageNum, pageSize);
        }
        IPage<InsuranceBO> insuranceBOPage = insuranceMapper.selectPage(page, wrapper);
        return insuranceBOPage.convert(item -> BeanUtil.toBean(item, InsuranceEntity.class));
    }

    @Override
    public List<InsuranceEntity> listInsurance(InsuranceEntity insuranceEntity) {
        Wrapper<InsuranceBO> wrapper = getInsuranceWrapper(insuranceEntity);
        if (wrapper == null) {
            return CollUtil.newArrayList();
        }
        List<InsuranceBO> insuranceBOList = insuranceMapper.selectList(wrapper);
        return BeanUtil.copyToList(insuranceBOList, InsuranceEntity.class);
    }

    @Override
    public void createInsurancePlans(List<InsurancePlanEntity> insurancePlanVOs) {
        List<InsurancePlanBO> insurancePlanBOList = BeanUtil.copyToList(insurancePlanVOs, InsurancePlanBO.class);
        List<BatchResult> results = insurancePlanMapper.insert(insurancePlanBOList);
        if (!MybatisUtil.isResultOk(results)) {
            throw new AppException(ResponseCode.INSURANCE_PLAN_CREATE_ERROR);
        }
        Map<Long, InsurancePlanEntity> collect = insurancePlanVOs.stream()
                .collect(Collectors.toMap(InsurancePlanEntity::getPlanNo, t -> t));
        insurancePlanBOList.forEach(item -> {
            InsurancePlanEntity insurancePlanVO = collect.get(item.getPlanNo());
            if (insurancePlanVO != null) {
                insurancePlanVO.setBaseEntity(item);
            }
        });
    }

    @Override
    public void saveBatchPlanEarnings(List<PlanEarningsEntity> planEarningsEntities) {
        List<PlanEarningsBO> planEarningsBOList = BeanUtil.copyToList(planEarningsEntities, PlanEarningsBO.class);
        List<BatchResult> results = planEarningsMapper.insert(planEarningsBOList);
        if (!MybatisUtil.isResultOk(results)) {
            throw new AppException(ResponseCode.INSURANCE_PLAN_CREATE_ERROR);
        }
    }

    @Override
    public void saveBatchPlanSafeguard(List<PlanSafeguardEntity> planSafeguardEntities) {
        List<PlanSafeguardBO> planSafeguardBOList = BeanUtil.copyToList(planSafeguardEntities, PlanSafeguardBO.class);
        List<BatchResult> results = planSafeguardMapper.insert(planSafeguardBOList);
        if (!MybatisUtil.isResultOk(results)) {
            throw new AppException(ResponseCode.INSURANCE_PLAN_CREATE_ERROR);
        }
    }

    @Override
    public List<InsurancePlanEntity> getPlansByInsuranceId(Long insuranceId) {
        Wrapper<InsurancePlanBO> wrapper = Wrappers.lambdaQuery(InsurancePlanBO.class)
                .eq(InsurancePlanBO::getInsuranceId, insuranceId);
        List<InsurancePlanBO> insurancePlanBOList = insurancePlanMapper.selectList(wrapper);
        return BeanUtil.copyToList(insurancePlanBOList, InsurancePlanEntity.class);
    }

    @Override
    public void deletePlanByPlanId(List<Long> planIds) {
        insurancePlanMapper.deleteByIds(planIds);
    }

    @Override
    public void deletePlanSafeguardByPlanId(List<Long> planIds) {
        Wrapper<PlanSafeguardBO> wrapper = Wrappers.lambdaQuery(PlanSafeguardBO.class)
                .in(PlanSafeguardBO::getPlanId, planIds);
        planSafeguardMapper.delete(wrapper);
    }

    @Override
    public void deletePlanEarningsByPlanId(List<Long> planIds) {
        Wrapper<PlanEarningsBO> wrapper = Wrappers.lambdaQuery(PlanEarningsBO.class)
                .in(PlanEarningsBO::getPlanId, planIds);
        planEarningsMapper.delete(wrapper);
    }

    @Override
    public List<InsuranceCoefficientEntity> findCoefficientList(InsuranceCoefficientEntity coefficientDTO) {
        Wrapper<InsuranceCoefficientBO> wrapper = getCoefficientWrapper(coefficientDTO);
        List<InsuranceCoefficientBO> selectList = insuranceCoefficientMapper.selectList(wrapper);
        return BeanUtil.copyToList(selectList, InsuranceCoefficientEntity.class);
    }

    @Override
    public List<InsurancePlanEntity> findPlanList(InsurancePlanEntity planDTO) {
        Wrapper<InsurancePlanBO> wrapper = getPlanWrapper(planDTO);
        List<InsurancePlanBO> selectList = insurancePlanMapper.selectList(wrapper);
        return BeanUtil.copyToList(selectList, InsurancePlanEntity.class);
    }

    @Override
    public List<InsuranceConditionEntity> findConditionList(InsuranceConditionEntity conditionDTO) {
        Wrapper<InsuranceConditionBO> wrapper = getConditionWrapper(conditionDTO);
        List<InsuranceConditionBO> insuranceConditionBOList = insuranceConditionMapper.selectList(wrapper);
        return BeanUtil.copyToList(insuranceConditionBOList, InsuranceConditionEntity.class);
    }

    @Override
    public List<PlanSafeguardEntity> findPlanSafeguardByPlanId(List<Long> planIds) {
        Wrapper<PlanSafeguardBO> wrapper = Wrappers.lambdaQuery(PlanSafeguardBO.class)
                .in(PlanSafeguardBO::getPlanId, planIds);
        List<PlanSafeguardBO> planSafeguardBOList = planSafeguardMapper.selectList(wrapper);
        return BeanUtil.copyToList(planSafeguardBOList, PlanSafeguardEntity.class);
    }

    @Override
    public List<PlanEarningsEntity> findPlanEarningsByPlanId(List<Long> planIds) {
        Wrapper<PlanEarningsBO> wrapper = Wrappers.lambdaQuery(PlanEarningsBO.class)
                .in(PlanEarningsBO::getPlanId, planIds);
        List<PlanEarningsBO> planEarningsBOList = planEarningsMapper.selectList(wrapper);
        return BeanUtil.copyToList(planEarningsBOList, PlanEarningsEntity.class);
    }

    @Override
    public void createInsuranceCoefficients(List<InsuranceCoefficientEntity> insuranceCoefficientVOs) {
        List<InsuranceCoefficientBO> insuranceCoefficientBOList = BeanUtil.copyToList(insuranceCoefficientVOs, InsuranceCoefficientBO.class);
        insuranceCoefficientMapper.insert(insuranceCoefficientBOList);
    }

    @Override
    public void deleteInsuranceCoefficientByInsuranceId(Long insuranceId) {
        Wrapper<InsuranceCoefficientBO> wrapper = Wrappers.lambdaQuery(InsuranceCoefficientBO.class)
                .eq(InsuranceCoefficientBO::getInsuranceId, insuranceId);
        insuranceCoefficientMapper.delete(wrapper);
    }

    @Override
    public void createInsuranceConditions(List<InsuranceConditionEntity> conditionEntities) {
        List<InsuranceConditionBO> insuranceConditionBOList = BeanUtil.copyToList(conditionEntities, InsuranceConditionBO.class);
        insuranceConditionMapper.insert(insuranceConditionBOList);
    }

    @Override
    public void deleteInsuranceConditionByInsuranceId(Long insuranceId) {
        Wrapper<InsuranceConditionBO> wrapper = Wrappers.lambdaQuery(InsuranceConditionBO.class)
                .eq(InsuranceConditionBO::getInsuranceId, insuranceId);
        insuranceConditionMapper.delete(wrapper);
    }

    /**
     * 获取 insurance wrapper
     *
     * @param insuranceEntity insurance entity
     * @return Wrapper
     */
    private Wrapper<InsuranceBO> getInsuranceWrapper(InsuranceEntity insuranceEntity) {
        LambdaQueryWrapper<InsuranceBO> wrapper = Wrappers.lambdaQuery(InsuranceBO.class)
                .eq(insuranceEntity.getCategoryNo() != null, InsuranceBO::getCategoryNo, insuranceEntity.getCategoryNo())
                .eq(insuranceEntity.getRecommendCategoryNo() != null, InsuranceBO::getRecommendCategoryNo, insuranceEntity.getRecommendCategoryNo())
                .likeRight(StringUtils.isNotBlank(insuranceEntity.getInsuranceName()), InsuranceBO::getInsuranceName, insuranceEntity.getInsuranceName())
                .eq(StringUtils.isNotBlank(insuranceEntity.getGoldSelection()), InsuranceBO::getGoldSelection, insuranceEntity.getGoldSelection())
                .eq(StringUtils.isNotBlank(insuranceEntity.getCarefree()), InsuranceBO::getCarefree, insuranceEntity.getCarefree())
                .eq(StringUtils.isNotBlank(insuranceEntity.getShowIndex()), InsuranceBO::getShowIndex, insuranceEntity.getShowIndex())
                .eq(insuranceEntity.getTimeStart() != null, InsuranceBO::getTimeStart, insuranceEntity.getTimeStart())
                .eq(StringUtils.isNotBlank(insuranceEntity.getTimeStartUnit()), InsuranceBO::getTimeStartUnit, insuranceEntity.getTimeStartUnit())
                .eq(insuranceEntity.getTimeEnd() != null, InsuranceBO::getTimeEnd, insuranceEntity.getTimeEnd())
                .eq(StringUtils.isNotBlank(insuranceEntity.getTimeEndUnit()), InsuranceBO::getTimeEndUnit, insuranceEntity.getTimeEndUnit())
                .eq(insuranceEntity.getRelation() != null, InsuranceBO::getRelation, insuranceEntity.getRelation())
                .eq(StringUtils.isNotBlank(insuranceEntity.getMultiple()), InsuranceBO::getMultiple, insuranceEntity.getMultiple())
                .eq(insuranceEntity.getContinuousInsuranceAge() != null, InsuranceBO::getContinuousInsuranceAge, insuranceEntity.getContinuousInsuranceAge())
                .eq(insuranceEntity.getCheckRule() != null, InsuranceBO::getCheckRule, insuranceEntity.getCheckRule())
                .eq(StringUtils.isNotBlank(insuranceEntity.getCompanyNo()), InsuranceBO::getCompanyNo, insuranceEntity.getCompanyNo())
                .eq(StringUtils.isNotBlank(insuranceEntity.getInsuranceState()), InsuranceBO::getInsuranceState, insuranceEntity.getInsuranceState())
                .eq(insuranceEntity.getGrace() != null, InsuranceBO::getGrace, insuranceEntity.getGrace())
                .eq(StringUtils.isNotBlank(insuranceEntity.getGraceUnit()), InsuranceBO::getGraceUnit, insuranceEntity.getGraceUnit())
                .eq(insuranceEntity.getRevival() != null, InsuranceBO::getRevival, insuranceEntity.getRevival())
                .eq(StringUtils.isNotBlank(insuranceEntity.getRevivalUnit()), InsuranceBO::getRevivalUnit, insuranceEntity.getRevivalUnit())
                .eq(insuranceEntity.getHesitation() != null, InsuranceBO::getHesitation, insuranceEntity.getHesitation())
                // 金牌保险优先展示 按创建时间降序
                .orderByAsc(InsuranceBO::getGoldSelection, InsuranceBO::getSortNo)
                .orderByDesc(InsuranceBO::getCreatedTime);
        if (CollUtil.isNotEmpty(insuranceEntity.getConditionVals())) {
            String conditionJson = JsonUtil.toJson(insuranceEntity.getConditionVals())
                    .replace("[", "")
                    .replace("]", "");
            Wrapper<InsuranceConditionBO> conditionWrapper = Wrappers.lambdaQuery(InsuranceConditionBO.class)
                    .apply("JSON_CONTAINS(condition_val, JSON_ARRAY(" + conditionJson + "))");
            List<InsuranceConditionBO> conditionBOList = insuranceConditionMapper.selectList(conditionWrapper);
            if (CollUtil.isEmpty(conditionBOList)) return null;
            List<Long> insuranceIds = conditionBOList.stream().map(InsuranceConditionBO::getInsuranceId).toList();
            wrapper.in(CollUtil.isNotEmpty(insuranceIds), InsuranceBO::getId, insuranceIds);
        }

        return wrapper;

    }

    /**
     * 获取保险计划查询条件
     *
     * @param planEntity 保险计划实体
     * @return Wrapper
     */
    private Wrapper<InsurancePlanBO> getPlanWrapper(InsurancePlanEntity planEntity) {
        return Wrappers.lambdaQuery(InsurancePlanBO.class)
                .eq(planEntity.getInsuranceId() != null, InsurancePlanBO::getInsuranceId, planEntity.getInsuranceId())
                .in(planEntity.getInsuranceIds() != null, InsurancePlanBO::getInsuranceId, MybatisUtil.convertCheckIds(planEntity.getInsuranceIds()))
                .eq(StringUtils.isNotBlank(planEntity.getPlanName()), InsurancePlanBO::getPlanName, planEntity.getPlanName())
                .eq(planEntity.getPrice() != null, InsurancePlanBO::getPrice, planEntity.getPrice())
                .eq(StringUtils.isNotBlank(planEntity.getPriceUnit()), InsurancePlanBO::getPriceUnit, planEntity.getPriceUnit())
                .eq(planEntity.getDataState() != null, InsurancePlanBO::getDataState, planEntity.getDataState())
                .orderByAsc(InsurancePlanBO::getSortNo)
                .orderByDesc(InsurancePlanBO::getCreatedTime);

    }

    /**
     * 获取保险系数查询条件
     *
     * @param conditionEntity 筛选实体
     * @return Wrapper
     */
    private Wrapper<InsuranceConditionBO> getConditionWrapper(InsuranceConditionEntity conditionEntity) {
        return Wrappers.lambdaQuery(InsuranceConditionBO.class)
                .eq(conditionEntity.getInsuranceId() != null, InsuranceConditionBO::getInsuranceId, conditionEntity.getInsuranceId())
                .in(conditionEntity.getInsuranceIds() != null, InsuranceConditionBO::getInsuranceId, MybatisUtil.convertCheckIds(conditionEntity.getInsuranceIds()))
                .eq(conditionEntity.getConditionKey() != null, InsuranceConditionBO::getConditionKey, conditionEntity.getConditionKey())
                .eq(conditionEntity.getSortNo() != null, InsuranceConditionBO::getSortNo, conditionEntity.getSortNo())
                .eq(conditionEntity.getDataState() != null, InsuranceConditionBO::getDataState, conditionEntity.getDataState())
                .orderByAsc(InsuranceConditionBO::getSortNo)
                .orderByDesc(InsuranceConditionBO::getCreatedTime);

    }

    /**
     * 获取系数wrapper
     *
     * @param coefficientEntity 系数实体
     * @return wrapper
     */
    private Wrapper<InsuranceCoefficientBO> getCoefficientWrapper(InsuranceCoefficientEntity coefficientEntity) {
        return Wrappers.lambdaQuery(InsuranceCoefficientBO.class)
                .eq(coefficientEntity.getInsuranceId() != null, InsuranceCoefficientBO::getInsuranceId, coefficientEntity.getInsuranceId())
                .in(coefficientEntity.getInstanceIds() != null, InsuranceCoefficientBO::getInsuranceId, MybatisUtil.convertCheckIds(coefficientEntity.getInstanceIds()))
                .eq(StringUtils.isNotBlank(coefficientEntity.getCoefficientKey()), InsuranceCoefficientBO::getCoefficientKey, coefficientEntity.getCoefficientKey())
                .eq(StringUtils.isNotBlank(coefficientEntity.getCoefficientValue()), InsuranceCoefficientBO::getCoefficientValue, coefficientEntity.getCoefficientValue())
                .eq(StringUtils.isNotBlank(coefficientEntity.getCoefficientType()), InsuranceCoefficientBO::getCoefficientType, coefficientEntity.getCoefficientType())
                .eq(coefficientEntity.getIsDefault() != null, InsuranceCoefficientBO::getIsDefault, coefficientEntity.getIsDefault())
                .eq(coefficientEntity.getIsShow() != null, InsuranceCoefficientBO::getIsShow, coefficientEntity.getIsShow())
                .eq(coefficientEntity.getScore() != null, InsuranceCoefficientBO::getScore, coefficientEntity.getScore())
                .eq(coefficientEntity.getDataState() != null, InsuranceCoefficientBO::getDataState, coefficientEntity.getDataState())
                .orderByAsc(InsuranceCoefficientBO::getSortNo);
    }

}
